<?php
namespace PsiFramework\Classes\Util\Object;

import("Classes.Model.ModelInterface.IPrimitiveObject");
import("Classes.Util.Database.Query.SqlType");

use \PsiFramework\Classes\Util\Database\Query\SqlType;
use \PsiFramework\Classes\Model\ModelInterface\IPrimitiveObject;

/**
 * PsiFramework
 * Php Simple Framework
 *
 * @author Rémi San
 * @version beta
 */

/**
 * The Date class is used to Manage Dates
 *
 * @package Util.Object
 */
class Date implements IPrimitiveObject
{

    protected /*int*/  $_year ;
    protected /*int*/  $_month ;
    protected /*int*/  $_day ;
    protected /*int*/  $_hour ;
    protected /*int*/  $_minute ;
    protected /*int*/  $_second ;
    
    protected /*bool*/ $_showTime;

    /**
     * Constructor
     *
     * @param string    $year        the year
     * @param string    $month        the month
     * @param string    $day        the day
     * @param string    $hour        the hours
     * @param string    $minute        the minutes
     * @param string    $second        the seconds
     */
    public function __construct(
        /*int*/  $year="0000",
        /*int*/  $month="00",
        /*int*/  $day="00",
        /*int*/  $hour="00",
        /*int*/  $minute="00",
        /*int*/  $second="00",
        /*bool*/ $showTime=true
    )
    {
        $this->_year = $year ;
        $this->_month = $month ;
        $this->_day = $day ;
        $this->_hour = $hour ;
        $this->_minute = $minute ;
        $this->_second = $second ;
        $this->_showTime = $showTime;
    }

    public static  function interval(Date $date, /*int*/ $seconds=0)
    {
        $dateString = date(
            "Y-m-d H:i:s",
            strtotime($date->getDateTime()) + $seconds
        );
        return Date::getDateFromString($dateString);
    }

    /**
     * Returns the date
     *
     * @return string the formatted date
     */
    public function getDate()
    {
        return $this->_year."-".$this->_month."-".$this->_day ;
    }

    /**
     * Returns the date
     *
     * @return string the dateTime
     */
    public function getDateTime()
    {
        if ((!isNullOrEmptyString($this->_year) && $this->_year != 0)
            || (!isNullOrEmptyString($this->_month) && $this->_month != 0)
            || (!isNullOrEmptyString($this->_day) && $this->_day != 0)
        ) {
            return  $this->_year."-".
                    $this->_month."-".
                    $this->_day." ".
                    $this->_hour.":".
                    $this->_minute.":".
                    $this->_second ;
        } else {
            return null ;
        }
    }

    /**
     * Getter for $year
     *
     * @return string    the year
     */
    public function getYear()
    {
        return $this->_year ;
    }

    /**
     * Getter for $month
     *
     * @return string    the month
     */
    public function getMonth()
    {
        return $this->_month ;
    }

    /**
     * Getter for $day
     *
     * @return string the day
     */
    public function getDay()
    {
        return $this->_day ;
    }

    /**
     * Getter for $hour
     *
     * @return string the hour
     */
    public function getHour()
    {
        return $this->_hour ;
    }

    /**
     * Getter for $minute
     *
     * @return string the minute
     */
    public function getMinute()
    {
        return $this->_minute ;
    }

    /**
     * Getter for $second
     *
     * @return string    the second
     */
    public function getSecond()
    {
        return $this->_second ;
    }

    /**
     * Return the difference of time in seconds between the
     * compare date and the current date
     *
     * @param Date the date to compare to
     * 
     * @return int the time passed
     */
    public function getTimePassed(/*Date*/ $date)
    {
        $currentTime = strtotime($this->getDateTime());
        $compareTime = strtotime($date->getDateTime());

        return $compareTime - $currentTime ;
    }
    
    public function getAddDelay(/*int*/ $years=0, /*int*/ $months=0, /*int*/ $days=0) {
        
        $thisTime = new \DateTime($this->getDateTime());
        $delayString = 'P';
        if ($years>0) {
            $delayString .= $years.'Y';
        }
        if ($months>0) {
            $delayString .= $months.'M';
        }
        if ($days>0) {
            $delayString .= $days.'D';
        }
        $interval = new \DateInterval($delayString);
        
        $thisTime->add($interval);
        
        $dateString = $thisTime->format('Y-m-d H:i:s');
        $date = self::getDateFromString($dateString);
        
        return $date;
    }
    
    public function addDelay(/*int*/ $years=0, /*int*/ $months=0, /*int*/ $days=0) {
        $date = $this->getAddDelay($years, $months, $days);
        
        $this->_year = $date->getYear();
        $this->_month = $date->getMonth();
        $this->_day = $date->getDay();
        $this->_hour = $date->getHour();
        $this->_minute = $date->getMinute();
        $this->_second = $date->getSecond();
    }
    
    public function addMonths(/*int*/ $months){
        $this->addDelay(0, $months, 0);
    }
    
    public function nextWeek(){
    	
        return $this->getAddDelay(0, 0, 7);
    }
    
    public function before(Date $date=null){
        if (is_null($date)) {
            return false ;
        } else {
            return $this->getTimePassed($date) > 0;
        }
    }
    
    public function after(Date $date=null){
        if (is_null($date)) {
            return false ;
        } else {
            return $this->getTimePassed($date) < 0;
        }
    }

    /**
     * Date as a string
     * 
     * @return string
     */
    public function toString()
    {
        $hourString = $this->_day.'/'.$this->_month.'/'.$this->_year ;
        if ($this->_showTime) {
            $hourString .= ' '.$this->_hour.':'.$this->_minute.':'.$this->_second ;
        }
        return $hourString;
    }

    public function __toString()
    {
        return $this->toString();
    }

    /**
     * Returns the Now date
     *
     * @return Date    the date corresponding to now
     */
    public static function now()
    {
        $dateString = date("Y-m-d H:i:s");
        return Date::getDateFromString($dateString);
    }

    /**
     * Returns the date
     *
     * @return Date    the date corresponding to the time passed
     */
    public static function time(/*int*/ $time)
    {
        $dateString = date("Y-m-d H:i:s", $time);
        return Date::getDateFromString($dateString);
    }

    public static function getDateFromFrenchString(/*string*/ $dateString)
    {
        $date = preg_split("[/]", $dateString);
        if (count($date)==3) {
            $year = $date[2] ;
            $month = $date[1] ;
            $day = $date[0] ;
    
            return new Date($year, $month, $day);
        } else {
            return null;
        }
    }

    public function buildDateFromString(/*string*/ $dateString)
    {
        if (is_null($dateString) || $dateString == 0) {
            throw new \Exception('Bad date format !');
        }

        $dateTime = preg_split("[ ]", $dateString);
        $date = preg_split("[-]", $dateTime[0]);
        $year = $date[0] ;
        $month = $date[1] ;
        $day = $date[2] ;

        $hour = "00" ;
        $minute = "00" ;
        $second = "00" ;
        if (isset($dateTime[1])) {
            $time = preg_split("[:]", $dateTime[1]);
            $hour = $time[0] ;
            $minute = $time[1] ;
            $second = $time[2] ;
        } else {
            $this->_showTime = false;
        }

        $this->_year = $year ;
        $this->_month = $month ;
        $this->_day = $day ;
        $this->_hour = $hour ;
        $this->_minute = $minute ;
        $this->_second = $second ;
    }

    /**
     * transforms a string to the date type
     *
     * @param     string     $dateString    the date string
     * @return    Date    the date
     */
    public static function getDateFromString(/*string*/ $dateString)
    {
        if (is_null($dateString) || $dateString == 0) {
            return null ;
        }

        $date = new Date();
        $date->buildDateFromString($dateString);

        return $date ;
    }

    public function serialize(/*boolean*/ $asText=true)
    {
        return $this->getDateTime();
    }

    public function unserialize(/*string*/ $text)
    {
        $this->buildDateFromString($text);
    }

    public static function getSqlType()
    {
        return SqlType::$dateTime ;
    }

}
